#include <iostream>
using namespace std;

/****************	Visitor.h	****************/
class Element;

class Visitor {
public:
    virtual ~Visitor() = default;

    virtual void VisitConcreteElementA(Element* elm) = 0;
    virtual void VisitConcreteElementB(Element* elm) {};
protected:
    Visitor() = default;
};

class Element {
public:
	Element(){};
    Element(string _name):name_(_name){};
    virtual ~Element(){};
    virtual void Accept(Visitor* vis) = 0;
	string name_;
};

class ConcreteVisitorA :public Visitor {
public:
    void VisitConcreteElementA(Element* elm){
		cout << "Visitor A will visit Element A..." << endl;
	}
    void VisitConcreteElementB(Element* elm){
		cout << "Visitor A will visit Element B..." << endl;
	}
};

class ConcreteVisitorB :public Visitor {
public:
    void VisitConcreteElementA(Element* elm){
		cout << "Visitor B will visit Element A..." << endl;
	}
    void VisitConcreteElementB(Element* elm){
		cout << "Visitor B will visit Element B..." << endl;
	}
};

class ConcreteElementA :public Element {
public:
	ConcreteElementA(string _name):Element(_name){};
    void Accept(Visitor* vis){
		// vis == ConcreteVisitorA / ConcreteVisitorB	即 访问者
		vis->VisitConcreteElementA(this);				// 访问具体对象	即自身
		cout << "ConcreteElementA : " << name_  <<  " visited" << endl;
	}
};

class ConcreteElementB :public Element {
public:
	ConcreteElementB(string _name):Element(_name){};
    void Accept(Visitor* vis){
		vis->VisitConcreteElementB(this);
		cout << "ConcreteElementB visited" << endl;
	}
};


int main() {
    Visitor *vis = new ConcreteVisitorB();
    Element *elm = new ConcreteElementA("xiaoming");
    elm->Accept(vis);

    delete elm;
    delete vis;

    return 0;
}
